use apikit_expand::api_attribute::{ApiHandlerAttr, ApiModuleAttr};
use proc_macro::TokenStream;
use syn::parse_macro_input;

macro_rules! convert_expand_result {
    ($e:expr) => {
        match $e {
            Ok(val) => val.into(),
            Err(err) => err.into_compile_error().into(),
        }
    };
}

/* #[proc_macro_derive(ApiModel)]
pub fn derive_api(input: TokenStream) -> TokenStream {
    let expand_result = glass_expand::reflect_derive::expand(&mut parse_macro_input!(input));
    convert_expand_result!(expand_result)
} */

#[proc_macro_attribute]
pub fn api(attr: TokenStream, item: TokenStream) -> TokenStream {
    let attr = parse_macro_input!(attr as ApiModuleAttr);
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = apikit_expand::api_attribute::api_expand(attr, item);
    convert_expand_result!(expand_result)
}

#[proc_macro_attribute]
pub fn module(attr: TokenStream, item: TokenStream) -> TokenStream {
    let attr = parse_macro_input!(attr as ApiModuleAttr);
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = apikit_expand::api_attribute::module_expand(attr, item);
    convert_expand_result!(expand_result)
}

#[proc_macro_attribute]
pub fn handler(attr: TokenStream, item: TokenStream) -> TokenStream {
    let attr = parse_macro_input!(attr as ApiHandlerAttr);
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = apikit_expand::api_attribute::handler_expand(attr, item);
    convert_expand_result!(expand_result)
}

#[proc_macro_derive(ApiModel, attributes(name, reflect))]
pub fn derive_model(input: TokenStream) -> TokenStream {
    let expand_result = apikit_expand::api_derive::model_expand(&mut parse_macro_input!(input));
    convert_expand_result!(expand_result)
}

#[proc_macro_derive(ApiError, attributes(status_code, from))]
pub fn derive_error(input: TokenStream) -> TokenStream {
    let expand_result = apikit_expand::error_deriver::error_expand(&mut parse_macro_input!(input));
    convert_expand_result!(expand_result)
}

#[proc_macro_derive(FormParts, attributes(form_data, try_from_multipart))]
pub fn form_parts(input: TokenStream) -> TokenStream {
    let expand_result = apikit_expand::form_parts_derive::expand(&mut parse_macro_input!(input));
    convert_expand_result!(expand_result)
}
